"""
=================
yoovo.servers.cgi
=================

A handler for serving through Apache's Common Gateway Interface.

"""

import os
import sys

def serve(application):
    """
    serve
    =====

    serve(application)
    Serve an application using the common gateway interface.

    'Stolen' from PEP 333_, which is in the public domain; cleaned up a bit to follow current pseudo-standards.

    .. _333: http://www.python.org/dev/peps/pep-0333/
    
    """
    if os.environ.get('BALLISTA_DEBUG'):
        import cgitb
        cgitb.enable()
    
    environ = dict(os.environ.items())
    environ['wsgi.input'] = sys.stdin
    environ['wsgi.errors'] = sys.stderr
    environ['wsgi.version'] = (1,0)
    environ['wsgi.multithread'] = False
    environ['wsgi.multiprocess'] = True
    environ['wsgi.run_once'] = True

    if environ.get('HTTPS','off') in ('on','1'):
        environ['wsgi.url_scheme'] = 'https'
    else:
        environ['wsgi.url_scheme'] = 'http'

    headers_set = []
    headers_sent = []
    def write(data):
        assert headers_set, Exception("Data written before ``start_response`` call.")
        if not headers_sent:
            # Before the first output, send the stored headers
            status, response_headers = headers_sent[:] = headers_set
            sys.stdout.write('Status: %s\n' % status)
            for header in response_headers:
                sys.stdout.write('%s: %s\n' % (header[0], header[1]))

            sys.stdout.write('\n')

        sys.stdout.write(data)
        sys.stdout.flush()

    def start_response(status, response_headers, exc_info=None):
        if exc_info:
            try:
                if headers_sent:
                    raise exc_info[0], exc_info[1], exc_info[2]
            finally:
                exc_info = None
        elif headers_set:
            raise AssertionError("Headers already set!")

        headers_set[:] = [status, response_headers]
        return write

    result = application(environ, start_response)
    try:
        for data in result:
            if data:
                write(data)
        if not headers_sent:
            write('')
    finally:
        if hasattr(result, 'close'):
            result.close()
